﻿
#include "MyVtkViewWindow.h"
#include <vtkLineSource.h>
#include <vtkInteractorStyleSwitch.h>
#include <vtkMultiProcessController.h>
#include <vtkCommunicator.h>
#include <vtkBillboardTextActor3D.h>
#include <vtkTextProperty.h>
#include <vtkFollower.h>

#include "MyVtkInteractorStyleZoom.h"
#include "MyVtkAxesActor.h"
#include "ActorManager.h"
#include "MyVtkInteractorSelect.h"


MyVtkViewWindow::MyVtkViewWindow(QWidget* parent):
    QVTKOpenGLNativeWidget(parent),
    m_pRenderer(nullptr),
    m_pRenderWindow(nullptr),
    m_pRenderWindowInteractor(nullptr),
    m_pAxesMarkerWidget(nullptr)
{
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());

    //创建vtk camera
    m_camera = vtkSmartPointer<vtkCamera>::New();
    m_camera->SetPosition(0, 0, 1);
    m_camera->SetFocalPoint(0, 0, 0);
    m_camera->SetViewUp(0, 1, 0);

    //创建vtk qt窗口
    m_pRenderer = vtkSmartPointer<vtkRenderer>::New();
    m_pRenderer->SetLayer(0);
    m_pRenderer->SetBackground(0.8, 0.8, 0.8);
    m_pRenderer->SetActiveCamera(m_camera);
    m_pRenderers.resize(0);
    m_pRenderers.push_back(m_pRenderer);


    //设置深度剥离
    m_pRenderer->SetUseDepthPeeling(GL_TRUE);     // 启用深度剥离
    m_pRenderer->SetMaximumNumberOfPeels(100); // 设置最大剥离次数
    m_pRenderer->SetOcclusionRatio(0);    // 设置遮挡比率，0表示不遮挡任何部分,1表示完全遮挡,值越大，渲染速率越慢。


    m_pRenderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    this->setRenderWindow(m_pRenderWindow);
    m_pRenderWindow->SetNumberOfLayers(m_pRenderers.size());
    m_pRenderWindow->AddRenderer(m_pRenderer);

    std::cout << "RenderingBackend = " << m_pRenderWindow->GetRenderingBackend() << std::endl;


    //渲染加速
    m_pRenderWindow->SetMultiSamples(0);//禁止多重采样
    m_pRenderer->SetUseShadows(GL_FALSE);//禁止渲染阴影



    //添加VTK OrientationMarkerWidget
    {
        m_pRenderWindowInteractor = m_pRenderWindow->GetInteractor();
        m_pAxesMarkerWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
        vtkSmartPointer<vtkAxesActor> pAxes = vtkSmartPointer<vtkAxesActor>::New();
        m_pAxesMarkerWidget->SetOrientationMarker(pAxes);
        m_pAxesMarkerWidget->SetInteractor(m_pRenderWindowInteractor);
        m_pAxesMarkerWidget->SetViewport(0.8, 0.0, 1.0, 0.2);
        m_pAxesMarkerWidget->SetEnabled(1);
        m_pAxesMarkerWidget->InteractiveOff();
    }

    //添加自定义的OrientationMarkerWidget
    {
        m_pRenderWindowInteractor = m_pRenderWindow->GetInteractor();
        m_pMyVtkOrientationMarkerWidget = vtkSmartPointer<MyVtkOrientationMarkerWidget>::New();

        vtkSmartPointer<MyVtkAxesActor> pAxes = vtkSmartPointer<MyVtkAxesActor>::New();
        pAxes->SetControledRenderer(m_pRenderer);
        pAxes->SetAxesMarkerWidget(m_pMyVtkOrientationMarkerWidget);

        m_pMyVtkOrientationMarkerWidget->SetAxesMarker(pAxes);
        m_pMyVtkOrientationMarkerWidget->SetOrientationMarker(pAxes);
        m_pMyVtkOrientationMarkerWidget->SetInteractor(m_pRenderWindowInteractor);
        m_pMyVtkOrientationMarkerWidget->SetViewport(0.7, 0.7, 1, 1);
        //m_pMyVtkOrientationMarkerWidget->SetViewport(0.4, 0.3, 1.0, 0.9);
        m_pMyVtkOrientationMarkerWidget->SetEnabled(1);
        //m_pMyVtkOrientationMarkerWidget->InteractiveOff();
    }

    //set interactor style
    {
        /*   vtkSmartPointer<vtkInteractorStyleSwitch> style = vtkSmartPointer<vtkInteractorStyleSwitch>::New();
           style->SetCurrentStyleToTrackballCamera();
           m_pRenderWindowInteractor->SetInteractorStyle(style);*/

           //   //设置自定义的缩放InteractorStyle
           //vtkSmartPointer<MyVtkInteractorStyleZoom>  zoomStyle = vtkSmartPointer<MyVtkInteractorStyleZoom>::New();
           //m_pRenderWindowInteractor->SetInteractorStyle(zoomStyle);

           //设置自定义的缩放InteractorStyle
        vtkSmartPointer<MyVtkInteractorSelect>  pickStyle = vtkSmartPointer<MyVtkInteractorSelect>::New();
        m_pRenderWindowInteractor->SetInteractorStyle(pickStyle);
    }


    m_pRenderer->ResetCamera();
}

MyVtkViewWindow::~MyVtkViewWindow()
{
}


MyVtkViewWindow* MyVtkViewWindow::GetInstance(QWidget* parent)
{
    static MyVtkViewWindow* instance = nullptr;
    if(instance == nullptr)
    {
        instance = new MyVtkViewWindow(parent);
    }

    return instance;
}

vtkRenderer* MyVtkViewWindow::GetRenderer()
{
    auto pActors = m_pRenderer->GetActors();
    pActors->InitTraversal();
    int actorsNum = pActors->GetNumberOfItems();

    if(actorsNum >= 1e8)
    {
        //创建vtk qt窗口
        m_pRenderer = vtkSmartPointer<vtkRenderer>::New();
        m_pRenderer->SetLayer(m_pRenderers.size());
        m_pRenderer->SetBackground(0.8, 0.8, 0.8);
        m_pRenderer->SetActiveCamera(m_camera);
        m_pRenderers.push_back(m_pRenderer);

        m_pRenderWindow->SetNumberOfLayers(m_pRenderers.size());
        m_pRenderWindow->AddRenderer(m_pRenderer);
    }

    return m_pRenderer;
}

void MyVtkViewWindow::ResetRenderersCamera()
{
    for(auto pRenderer : m_pRenderers)
    {
        pRenderer->ResetCamera();
    }
}

void MyVtkViewWindow::SetViewType(EViewType type)
{
    auto pVtkViewWindow = GetInstance();
    if(pVtkViewWindow == nullptr)
    {
        return;
    }

    auto pRenderer = pVtkViewWindow->GetRenderer();
    vtkActorCollection* pActors = pRenderer->GetActors();
    int actorsNum = pActors->GetNumberOfItems();
    pActors->InitTraversal();

    //遍历 pActors
    for(int i = 0; i < actorsNum; i++)
    {
        vtkActor* pActor = vtkActor::SafeDownCast(pActors->GetNextItem());

        if(pActor == nullptr)
        {
            continue;
        }

        pActor->GetProperty()->SetLineWidth(5);
        pActor->GetProperty()->SetPointSize(14);

        switch(type)
        {
        case MyVtkViewWindow::E_VIEW_TYPE_VERTEX:
            pActor->GetProperty()->VertexVisibilityOn();
            pActor->GetProperty()->EdgeVisibilityOff();
            pActor->VisibilityOn();
            break;

        case MyVtkViewWindow::E_VIEW_TYPE_EDGE:
            pActor->GetProperty()->VertexVisibilityOff();
            pActor->GetProperty()->EdgeVisibilityOn();
            pActor->VisibilityOn();

            break;

        case MyVtkViewWindow::E_VIEW_TYPE_FACE:
            pActor->GetProperty()->VertexVisibilityOff();
            pActor->GetProperty()->EdgeVisibilityOff();
            pActor->VisibilityOn();
            break;
        }
    }

    pRenderer->ResetCamera();
    pVtkViewWindow->GetRenderWindow()->Render();
}




